/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.openide.text;
import java.io.*;
import javax.swing.text.Position;
import javax.swing.text.StyledDocument;
import javax.swing.text.BadLocationException;
import org.openide.util.NbBundle;
/** A range bounded by two {@link PositionRef}s.
*
* @author Petr Hamernik
*/
public final class PositionBounds extends Object implements Serializable {
static final long serialVersionUID = 3338509625548836633L;
/** Begin */
private PositionRef begin;
/** End */
private PositionRef end;
/** Creates new <code>PositionBounds</code>.
* @param begin the start position of the range
* @param end the end position of the range
*/
public PositionBounds(PositionRef begin, PositionRef end) {
this.begin = begin;
this.end = end;
}
/**
* Get the starting position of this range.
* @return the begin position
*/
public PositionRef getBegin() {
return begin;
}
/**
* Get the ending position of this range.
* @return the end position
*/
public PositionRef getEnd() {
return end;
}
/** Replaces the text contained in this range.
* This replacement is done atomically, and so is preferable to manual inserts & removes.
* <p>If you are running this from user-oriented code, you may want to wrap it in {@link NbDocument#runAtomicAsUser}.
* @param text new text to insert over existing text
* @exception IOException if any problem occurred during document loading (if that was necessary)
* @exception BadLocationException if the positions are out of the bounds of the document
*/
public void setText(final String text) throws IOException, BadLocationException {
final StyledDocument doc = begin.getEditorSupport().openDocument();
final BadLocationException[] hold = new BadLocationException[] { null };
Runnable run = new Runnable() {
public void run() {
try {
int p1 = begin.getOffset();
int p2 = end.getOffset();
int len = text.length();
if (len == 0) { // 1) set empty string
if (p2 > p1)
doc.remove(p1, p2 - p1);
}
else { // 2) set non empty string
if (p2 - p1 >= 2) {
doc.insertString(p1 + 1, text, null);
doc.remove(p1 + 1 + len, p2 - p1 - 1);
doc.remove(p1, 1);
}
else {
doc.insertString(p1, text, null);
if (p2 > p1)
doc.remove(p1 + len, p2 - p1);
}
}
}
catch (BadLocationException e) {
hold[0] = e;
}
}
};
NbDocument.runAtomic (doc, run);
if (hold[0] != null)
throw hold[0];
}
/** Inserts the text after this PositionBounds.
* @param text The text to insert. The text must not be empty.
* @return the range of inserted text.
* @exception IOException if any problem occurred during document loading (if that was necessary)
* @exception BadLocationException if the positions are out of the bounds of the document
*/
public PositionBounds insertAfter(final String text) throws IOException, BadLocationException {
if (text.length() == 0)
throw new BadLocationException(NbBundle.getBundle(PositionBounds.class).getString("MSG_Empty_string"),
begin.getOffset());
final EditorSupport editor = begin.getEditorSupport();
final StyledDocument doc = editor.openDocument();
final Object[] hold = new Object[] { null, null };
Runnable run = new Runnable() {
public void run() {
synchronized (editor.getLock()) {
/* editor.getLock(): fixes deadlock - this lock is acquired later anyhow,
so we are changing the order in which the locks are acquired */
try {
int p1 = end.getOffset();
int p2 = p1 + text.length();
doc.insertString (p1, text, null);
end = editor.createPositionRef(p1, end.getPositionBias());
PositionRef posBegin = editor.createPositionRef(p1, Position.Bias.Forward);
PositionRef posEnd = editor.createPositionRef(p2, Position.Bias.Backward);
hold[1] = new PositionBounds(posBegin, posEnd);
}
catch (BadLocationException e) {
hold[0] = e;
}
}
}
};
NbDocument.runAtomic (doc, run);
if (hold[0] != null)
throw (BadLocationException) hold[0];
else
return (PositionBounds) hold[1];
}
/** Finds the text contained in this range.
* @return the text
* @exception IOException if any I/O problem occurred during document loading (if that was necessary)
* @exception BadLocationException if the positions are out of the bounds of the document
*/
public String getText() throws BadLocationException, IOException {
StyledDocument doc = begin.getEditorSupport().openDocument();
int p1 = begin.getOffset();
int p2 = end.getOffset();
return doc.getText(p1, p2 - p1);
}
/* @return the bounds as the string. */
public String toString() {
StringBuffer buf = new StringBuffer("Position bounds["); // NOI18N
try {
String content = getText();
buf.append(begin);
buf.append(","); // NOI18N
buf.append(end);
buf.append(",\""); // NOI18N
buf.append(content);
buf.append("\""); // NOI18N
}
catch (IOException e) {
buf.append("Invalid: "); // NOI18N
buf.append(e.getMessage());
}
catch (BadLocationException e) {
buf.append("Invalid: "); // NOI18N
buf.append(e.getMessage());
}
buf.append("]"); // NOI18N
return buf.toString();
}
}